<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js light">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>类型布局 </title>
        
        


        <!-- Custom HTML head -->
        


        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        
        <link rel="icon" href="favicon.svg">
        
        
        <link rel="shortcut icon" href="favicon.png">
        
        <link rel="stylesheet" href="css/variables.css">
        <link rel="stylesheet" href="css/general.css">
        <link rel="stylesheet" href="css/chrome.css">
        <link rel="stylesheet" href="css/print.css" media="print">

        <!-- Fonts -->
        <link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
        
        <link rel="stylesheet" href="fonts/fonts.css">
        

        <!-- Highlight.js Stylesheets -->
        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        
        <link rel="stylesheet" href="theme/reference.css">
        

        
    </head>
    <body>
        <!-- Provide site root to javascript -->
        <script type="text/javascript">
            var path_to_root = "";
            var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
        </script>

        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
            if (theme === null || theme === undefined) { theme = default_theme; }
            var html = document.querySelector('html');
            html.classList.remove('no-js')
            html.classList.remove('light')
            html.classList.add(theme);
            html.classList.add('js');
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <div class="sidebar-scrollbox">
                <ol class="chapter"><li class="chapter-item expanded affix "><a href="翻译说明.html">翻译说明</a></li><li class="chapter-item expanded affix "><a href="introduction.html">介绍</a></li><li class="chapter-item expanded "><a href="notation.html"><strong aria-hidden="true">1.</strong> 表义符</a></li><li class="chapter-item expanded "><a href="lexical-structure.html"><strong aria-hidden="true">2.</strong> 词法结构</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="input-format.html"><strong aria-hidden="true">2.1.</strong> 输入格式</a></li><li class="chapter-item expanded "><a href="keywords.html"><strong aria-hidden="true">2.2.</strong> 关键字</a></li><li class="chapter-item expanded "><a href="identifiers.html"><strong aria-hidden="true">2.3.</strong> 标识符</a></li><li class="chapter-item expanded "><a href="comments.html"><strong aria-hidden="true">2.4.</strong> 注释</a></li><li class="chapter-item expanded "><a href="whitespace.html"><strong aria-hidden="true">2.5.</strong> 空白符</a></li><li class="chapter-item expanded "><a href="tokens.html"><strong aria-hidden="true">2.6.</strong> token</a></li></ol></li><li class="chapter-item expanded "><a href="macros.html"><strong aria-hidden="true">3.</strong> 宏</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="macros-by-example.html"><strong aria-hidden="true">3.1.</strong> 声明宏</a></li><li class="chapter-item expanded "><a href="procedural-macros.html"><strong aria-hidden="true">3.2.</strong> 过程宏</a></li></ol></li><li class="chapter-item expanded "><a href="crates-and-source-files.html"><strong aria-hidden="true">4.</strong> crate 和源文件</a></li><li class="chapter-item expanded "><a href="conditional-compilation.html"><strong aria-hidden="true">5.</strong> 条件编译</a></li><li class="chapter-item expanded "><a href="items.html"><strong aria-hidden="true">6.</strong> 程序项</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="items/modules.html"><strong aria-hidden="true">6.1.</strong> 模块</a></li><li class="chapter-item expanded "><a href="items/extern-crates.html"><strong aria-hidden="true">6.2.</strong> 外部crate</a></li><li class="chapter-item expanded "><a href="items/use-declarations.html"><strong aria-hidden="true">6.3.</strong> use声明</a></li><li class="chapter-item expanded "><a href="items/functions.html"><strong aria-hidden="true">6.4.</strong> 函数</a></li><li class="chapter-item expanded "><a href="items/type-aliases.html"><strong aria-hidden="true">6.5.</strong> 类型别名</a></li><li class="chapter-item expanded "><a href="items/structs.html"><strong aria-hidden="true">6.6.</strong> 结构体</a></li><li class="chapter-item expanded "><a href="items/enumerations.html"><strong aria-hidden="true">6.7.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="items/unions.html"><strong aria-hidden="true">6.8.</strong> 联合体</a></li><li class="chapter-item expanded "><a href="items/constant-items.html"><strong aria-hidden="true">6.9.</strong> 常量项</a></li><li class="chapter-item expanded "><a href="items/static-items.html"><strong aria-hidden="true">6.10.</strong> 静态项</a></li><li class="chapter-item expanded "><a href="items/traits.html"><strong aria-hidden="true">6.11.</strong> trait</a></li><li class="chapter-item expanded "><a href="items/implementations.html"><strong aria-hidden="true">6.12.</strong> 实现</a></li><li class="chapter-item expanded "><a href="items/external-blocks.html"><strong aria-hidden="true">6.13.</strong> 外部块</a></li><li class="chapter-item expanded "><a href="items/generics.html"><strong aria-hidden="true">6.14.</strong> 泛型参数</a></li><li class="chapter-item expanded "><a href="items/associated-items.html"><strong aria-hidden="true">6.15.</strong> 关联程序项</a></li></ol></li><li class="chapter-item expanded "><a href="attributes.html"><strong aria-hidden="true">7.</strong> 属性</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="attributes/testing.html"><strong aria-hidden="true">7.1.</strong> 测试</a></li><li class="chapter-item expanded "><a href="attributes/derive.html"><strong aria-hidden="true">7.2.</strong> 派生</a></li><li class="chapter-item expanded "><a href="attributes/diagnostics.html"><strong aria-hidden="true">7.3.</strong> 诊断</a></li><li class="chapter-item expanded "><a href="attributes/codegen.html"><strong aria-hidden="true">7.4.</strong> 代码生成</a></li><li class="chapter-item expanded "><a href="attributes/limits.html"><strong aria-hidden="true">7.5.</strong> 极限值设置</a></li><li class="chapter-item expanded "><a href="attributes/type_system.html"><strong aria-hidden="true">7.6.</strong> 类型系统</a></li></ol></li><li class="chapter-item expanded "><a href="statements-and-expressions.html"><strong aria-hidden="true">8.</strong> 语句和表达式</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="statements.html"><strong aria-hidden="true">8.1.</strong> 语句</a></li><li class="chapter-item expanded "><a href="expressions.html"><strong aria-hidden="true">8.2.</strong> 表达式</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="expressions/literal-expr.html"><strong aria-hidden="true">8.2.1.</strong> 字面量表达式</a></li><li class="chapter-item expanded "><a href="expressions/path-expr.html"><strong aria-hidden="true">8.2.2.</strong> 路径表达式</a></li><li class="chapter-item expanded "><a href="expressions/block-expr.html"><strong aria-hidden="true">8.2.3.</strong> 块表达式</a></li><li class="chapter-item expanded "><a href="expressions/operator-expr.html"><strong aria-hidden="true">8.2.4.</strong> 运算符表达式</a></li><li class="chapter-item expanded "><a href="expressions/grouped-expr.html"><strong aria-hidden="true">8.2.5.</strong> 分组表达式</a></li><li class="chapter-item expanded "><a href="expressions/array-expr.html"><strong aria-hidden="true">8.2.6.</strong> 数组和索引表达式</a></li><li class="chapter-item expanded "><a href="expressions/tuple-expr.html"><strong aria-hidden="true">8.2.7.</strong> 元组和索引表达式</a></li><li class="chapter-item expanded "><a href="expressions/struct-expr.html"><strong aria-hidden="true">8.2.8.</strong> 结构体表达式</a></li><li class="chapter-item expanded "><a href="expressions/call-expr.html"><strong aria-hidden="true">8.2.9.</strong> 调用表达式</a></li><li class="chapter-item expanded "><a href="expressions/method-call-expr.html"><strong aria-hidden="true">8.2.10.</strong> 方法调用表达式</a></li><li class="chapter-item expanded "><a href="expressions/field-expr.html"><strong aria-hidden="true">8.2.11.</strong> 字段访问表达式</a></li><li class="chapter-item expanded "><a href="expressions/closure-expr.html"><strong aria-hidden="true">8.2.12.</strong> 闭包表达式</a></li><li class="chapter-item expanded "><a href="expressions/loop-expr.html"><strong aria-hidden="true">8.2.13.</strong> 循环表达式</a></li><li class="chapter-item expanded "><a href="expressions/range-expr.html"><strong aria-hidden="true">8.2.14.</strong> 区间表达式</a></li><li class="chapter-item expanded "><a href="expressions/if-expr.html"><strong aria-hidden="true">8.2.15.</strong> if 和 if let 表达式</a></li><li class="chapter-item expanded "><a href="expressions/match-expr.html"><strong aria-hidden="true">8.2.16.</strong> 匹配表达式</a></li><li class="chapter-item expanded "><a href="expressions/return-expr.html"><strong aria-hidden="true">8.2.17.</strong> 返回表达式</a></li><li class="chapter-item expanded "><a href="expressions/await-expr.html"><strong aria-hidden="true">8.2.18.</strong> 等待(await)表达式</a></li></ol></li></ol></li><li class="chapter-item expanded "><a href="patterns.html"><strong aria-hidden="true">9.</strong> 模式</a></li><li class="chapter-item expanded "><a href="type-system.html"><strong aria-hidden="true">10.</strong> 类型系统</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="types.html"><strong aria-hidden="true">10.1.</strong> 类型</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="types/boolean.html"><strong aria-hidden="true">10.1.1.</strong> 布尔型</a></li><li class="chapter-item expanded "><a href="types/numeric.html"><strong aria-hidden="true">10.1.2.</strong> 数字型</a></li><li class="chapter-item expanded "><a href="types/textual.html"><strong aria-hidden="true">10.1.3.</strong> 字符型</a></li><li class="chapter-item expanded "><a href="types/never.html"><strong aria-hidden="true">10.1.4.</strong> never类型</a></li><li class="chapter-item expanded "><a href="types/tuple.html"><strong aria-hidden="true">10.1.5.</strong> 元组</a></li><li class="chapter-item expanded "><a href="types/array.html"><strong aria-hidden="true">10.1.6.</strong> 数组</a></li><li class="chapter-item expanded "><a href="types/slice.html"><strong aria-hidden="true">10.1.7.</strong> 切片</a></li><li class="chapter-item expanded "><a href="types/struct.html"><strong aria-hidden="true">10.1.8.</strong> 结构体</a></li><li class="chapter-item expanded "><a href="types/enum.html"><strong aria-hidden="true">10.1.9.</strong> 枚举</a></li><li class="chapter-item expanded "><a href="types/union.html"><strong aria-hidden="true">10.1.10.</strong> 联合体</a></li><li class="chapter-item expanded "><a href="types/function-item.html"><strong aria-hidden="true">10.1.11.</strong> 函数项类型</a></li><li class="chapter-item expanded "><a href="types/closure.html"><strong aria-hidden="true">10.1.12.</strong> 闭包</a></li><li class="chapter-item expanded "><a href="types/pointer.html"><strong aria-hidden="true">10.1.13.</strong> 指针型</a></li><li class="chapter-item expanded "><a href="types/function-pointer.html"><strong aria-hidden="true">10.1.14.</strong> 函数指针</a></li><li class="chapter-item expanded "><a href="types/trait-object.html"><strong aria-hidden="true">10.1.15.</strong> trait对象</a></li><li class="chapter-item expanded "><a href="types/impl-trait.html"><strong aria-hidden="true">10.1.16.</strong> 实现trait</a></li><li class="chapter-item expanded "><a href="types/parameters.html"><strong aria-hidden="true">10.1.17.</strong> 类型参数</a></li><li class="chapter-item expanded "><a href="types/inferred.html"><strong aria-hidden="true">10.1.18.</strong> 推断型</a></li></ol></li><li class="chapter-item expanded "><a href="dynamically-sized-types.html"><strong aria-hidden="true">10.2.</strong> 动态尺寸类型(DST)</a></li><li class="chapter-item expanded "><a href="type-layout.html" class="active"><strong aria-hidden="true">10.3.</strong> 类型布局 </a></li><li class="chapter-item expanded "><a href="interior-mutability.html"><strong aria-hidden="true">10.4.</strong> 内部可变性</a></li><li class="chapter-item expanded "><a href="subtyping.html"><strong aria-hidden="true">10.5.</strong> 子类型和型变</a></li><li class="chapter-item expanded "><a href="trait-bounds.html"><strong aria-hidden="true">10.6.</strong> trait约束及其生存期约束</a></li><li class="chapter-item expanded "><a href="type-coercions.html"><strong aria-hidden="true">10.7.</strong> 类型自动强转</a></li><li class="chapter-item expanded "><a href="destructors.html"><strong aria-hidden="true">10.8.</strong> 析构函数</a></li><li class="chapter-item expanded "><a href="lifetime-elision.html"><strong aria-hidden="true">10.9.</strong> 生存期省略</a></li></ol></li><li class="chapter-item expanded "><a href="special-types-and-traits.html"><strong aria-hidden="true">11.</strong> 特殊类型和 trait</a></li><li class="chapter-item expanded "><a href="names.html"><strong aria-hidden="true">12.</strong> 名称</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="names/namespaces.html"><strong aria-hidden="true">12.1.</strong> 命名空间</a></li><li class="chapter-item expanded "><a href="names/scopes.html"><strong aria-hidden="true">12.2.</strong> 作用域</a></li><li class="chapter-item expanded "><a href="names/preludes.html"><strong aria-hidden="true">12.3.</strong> 预导入包</a></li><li class="chapter-item expanded "><a href="paths.html"><strong aria-hidden="true">12.4.</strong> 路径</a></li><li class="chapter-item expanded "><a href="names/name-resolution.html"><strong aria-hidden="true">12.5.</strong> 名称解析</a></li><li class="chapter-item expanded "><a href="visibility-and-privacy.html"><strong aria-hidden="true">12.6.</strong> 可见性与隐私权</a></li></ol></li><li class="chapter-item expanded "><a href="memory-model.html"><strong aria-hidden="true">13.</strong> 内存模型</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="memory-allocation-and-lifetime.html"><strong aria-hidden="true">13.1.</strong> 内存分配和生存期</a></li><li class="chapter-item expanded "><a href="variables.html"><strong aria-hidden="true">13.2.</strong> 变量</a></li></ol></li><li class="chapter-item expanded "><a href="linkage.html"><strong aria-hidden="true">14.</strong> 链接(linkage)</a></li><li class="chapter-item expanded "><a href="unsafety.html"><strong aria-hidden="true">15.</strong> 非安全性</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="unsafe-functions.html"><strong aria-hidden="true">15.1.</strong> 非安全函数</a></li><li class="chapter-item expanded "><a href="unsafe-blocks.html"><strong aria-hidden="true">15.2.</strong> 非安全代码块</a></li><li class="chapter-item expanded "><a href="behavior-considered-undefined.html"><strong aria-hidden="true">15.3.</strong> 未定义行为</a></li><li class="chapter-item expanded "><a href="behavior-not-considered-unsafe.html"><strong aria-hidden="true">15.4.</strong> 不被认为是非安全的行为</a></li></ol></li><li class="chapter-item expanded "><a href="const_eval.html"><strong aria-hidden="true">16.</strong> 常量求值</a></li><li class="chapter-item expanded "><a href="abi.html"><strong aria-hidden="true">17.</strong> ABI</a></li><li class="chapter-item expanded "><a href="runtime.html"><strong aria-hidden="true">18.</strong> Rust运行时</a></li><li class="chapter-item expanded "><a href="appendices.html"><strong aria-hidden="true">19.</strong> 附录</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="macro-ambiguity.html"><strong aria-hidden="true">19.1.</strong> 宏定义规范</a></li><li class="chapter-item expanded "><a href="influences.html"><strong aria-hidden="true">19.2.</strong> 影响来源</a></li><li class="chapter-item expanded "><a href="glossary.html"><strong aria-hidden="true">19.3.</strong> 术语表</a></li><li class="chapter-item expanded "><a href="本书术语翻译对照表.html"><strong aria-hidden="true">19.4.</strong> 本书术语翻译对照表</a></li></ol></li></ol>
            </div>
            <div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar-hover-placeholder"></div>
                <div id="menu-bar" class="menu-bar sticky bordered">
                    <div class="left-buttons">
                        <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                            <i class="fa fa-bars"></i>
                        </button>
                        <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                            <i class="fa fa-paint-brush"></i>
                        </button>
                        <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                            <li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                            <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                        </ul>
                        
                        <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                            <i class="fa fa-search"></i>
                        </button>
                        
                    </div>

                    <h1 class="menu-title"></h1>

                    <div class="right-buttons">
                        <a href="print.html" title="Print this book" aria-label="Print this book">
                            <i id="print-button" class="fa fa-print"></i>
                        </a>
                        
                        <a href="https://gitee.com/minstrel1977/rust-reference" title="Git repository" aria-label="Git repository">
                            <i id="git-repository-button" class="fa fa-github"></i>
                        </a>
                        
                    </div>
                </div>

                
                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <h1><a class="header" href="#type-layout" id="type-layout">Type Layout</a></h1>
<h1><a class="header" href="#类型布局" id="类型布局">类型布局</a></h1>
<blockquote>
<p><a href="https://github.com/rust-lang/reference/blob/master/src/type-layout.md">type-layout.md</a><br />
commit: 0cb7e46722353a5de852d03684b4895516f92a4d <br />
本章译文最后维护日期：2021-06-27</p>
</blockquote>
<p>类型的布局描述类型的尺寸(size)、对齐量(alignment)和字段(fields)的<em>相对偏移量(relative offsets)</em>。对于枚举，其判别值(discriminant)的布局和解释也是类型布局的一部分。</p>
<p>每次编译都有可能更改类型布局。这里我们只阐述当前编译器所保证的内容，而没试图去阐述编译器对此做了什么。</p>
<h2><a class="header" href="#size-and-alignment" id="size-and-alignment">Size and Alignment</a></h2>
<h2><a class="header" href="#尺寸和对齐量" id="尺寸和对齐量">尺寸和对齐量</a></h2>
<p>所有值都有对一个齐量和尺寸。</p>
<p>值的<em>对齐量</em>指定了哪些地址可以有效地存储该值。对齐量为 <code>n</code> 的值只能存储地址为 n 的倍数的内存地址上。例如，对齐量为 2 的值必须存储在偶数地址上，而对齐量为 1 的值可以存储在任何地址上。对齐量是用字节数来度量的，必须至少是 1，并且总是 2 的幂次。值的对齐量可以通过函数 <a href="https://doc.rust-lang.org/std/mem/fn.align_of_val.html"><code>align_of_val</code></a> 来检测。</p>
<p>值的<em>尺寸</em>是同类型的值组成的数组中连续两个元素之间的字节偏移量，此偏移量包括了为保持程序项类型内部对齐而对此类型做的对齐填充。值的尺寸总是其对齐量的非负整数倍数。值的尺寸可以通过函数 <a href="https://doc.rust-lang.org/std/mem/fn.size_of_val.html"><code>size_of_val</code></a> 来检测。</p>
<p>如果某类型的所有的值都具有相同的尺寸和对齐量，并且两者在编译时都是已知的，并且实现了 <a href="https://doc.rust-lang.org/std/marker/trait.Sized.html"><code>Sized</code></a> trait，则可以使用函数 <a href="https://doc.rust-lang.org/std/mem/fn.size_of.html"><code>size_of</code></a> 和 <a href="https://doc.rust-lang.org/std/mem/fn.align_of.html"><code>align_of</code></a> 对此类型进行检测。没有实现 <code>Sized</code> trait 的类型被称为<a href="dynamically-sized-types.html">动态尺寸类型</a>。由于实现了 <code>Sized</code> trait 的某一类型的所有值共享相同的尺寸和对齐量，所以我们分别将这俩共享值称为该类型的尺寸和该类型的对齐量。</p>
<h2><a class="header" href="#primitive-data-layout" id="primitive-data-layout">Primitive Data Layout</a></h2>
<h2><a class="header" href="#原生类型的布局" id="原生类型的布局">原生类型的布局</a></h2>
<p>下表给出了大多数原生类型(primitives)的尺寸。</p>
<table><thead><tr><th>类型</th><th><code>size_of::&lt;Type&gt;()</code></th></tr></thead><tbody>
<tr><td><code>bool</code></td><td>1</td></tr>
<tr><td><code>u8</code> / <code>i8</code></td><td>1</td></tr>
<tr><td><code>u16</code> / <code>i16</code></td><td>2</td></tr>
<tr><td><code>u32</code> / <code>i32</code></td><td>4</td></tr>
<tr><td><code>u64</code> / <code>i64</code></td><td>8</td></tr>
<tr><td><code>u128</code> / <code>i128</code></td><td>16</td></tr>
<tr><td><code>f32</code></td><td>4</td></tr>
<tr><td><code>f64</code></td><td>8</td></tr>
<tr><td><code>char</code></td><td>4</td></tr>
</tbody></table>
<p><code>usize</code> 和 <code>isize</code> 的尺寸足以包含目标平台上的每个内存地址。例如，在 32-bit 目标上，它们是 4 个字节，而在 64-bit 目标上，它们是 8 个字节。</p>
<p>大多数原生类型的对齐量通常与它们的尺寸保持一致，尽管这是特定于平台的行为。比较典型的就是在 x86 平台上，u64 和 f64 都上 32-bit 的对齐量。</p>
<h2><a class="header" href="#pointers-and-references-layout" id="pointers-and-references-layout">Pointers and References Layout</a></h2>
<h2><a class="header" href="#指针和引用的布局" id="指针和引用的布局">指针和引用的布局</a></h2>
<p>指针和引用具有相同的布局。指针或引用的可变性不会影响其布局。</p>
<p>指向固定尺寸类型(sized type)的值的指针具有和 <code>usize</code> 相同的尺寸和对齐量。</p>
<p>指向非固定尺寸类型(unsized types)的值的指针是固定尺寸的。其尺寸和对齐量至少等于一个指针的尺寸和对齐量</p>
<blockquote>
<p>注意：虽然不应该依赖于此，但是目前所有指向 <abbr title="Dynamically Sized Types">DST</abbr> 的指针都是 <code>usize</code> 的两倍尺寸，并且具有相同的对齐量。</p>
</blockquote>
<h2><a class="header" href="#array-layout" id="array-layout">Array Layout</a></h2>
<h2><a class="header" href="#数组的布局" id="数组的布局">数组的布局</a></h2>
<p>数组 <code>[T; N]</code> 的尺寸为 <code>size_of::&lt;T&gt;() * N</code>，对齐量和 <code>T</code> 的对齐量相同。所以数组的布局使得数组的第 n 个(<code>nth</code>)元素（其中索引 n 是从0开始的）为从数组开始的位置向后偏移 <code>n * size_of::&lt;T&gt;()</code> 个字节数。</p>
<h2><a class="header" href="#slice-layout" id="slice-layout">Slice Layout</a></h2>
<h2><a class="header" href="#切片的布局" id="切片的布局">切片的布局</a></h2>
<p>切片的布局与它们所切的那部分数组片段相同。</p>
<blockquote>
<p>注意：这是关于原生的 <code>[T]</code>类型，而不是指向切片的指针（<code>&amp;[T]</code>、<code>Box&lt;[T]&gt;</code> 等）。</p>
</blockquote>
<h2><a class="header" href="#str-layout" id="str-layout"><code>str</code> Layout</a></h2>
<h2><a class="header" href="#字符串切片str的布局" id="字符串切片str的布局">字符串切片(<code>str</code>)的布局</a></h2>
<p>字符串切片是一种 UTF-8 表示形式(representation)的字符序列，它们与 <code>[u8]</code>类型的切片拥有相同的类型布局。</p>
<h2><a class="header" href="#tuple-layout" id="tuple-layout">Tuple Layout</a></h2>
<h2><a class="header" href="#元组的布局" id="元组的布局">元组的布局</a></h2>
<p>元组对于其布局没有任何保证。</p>
<p>一个例外情况是单元结构体(unit tuple)(<code>()</code>)类型，它被保证为尺寸为 0，对齐量为 1。</p>
<h2><a class="header" href="#trait-object-layout" id="trait-object-layout">Trait Object Layout</a></h2>
<h2><a class="header" href="#trait对象的布局" id="trait对象的布局">trait对象的布局</a></h2>
<p>trait对象的布局与 trait对象的值相同。</p>
<blockquote>
<p>注意：这是关于原生 trait对象类型(raw trait object type)的，而不是指向 trait对象的指针（<code>&amp;dyn Trait</code>， <code>Box&lt;dyn Trait&gt;</code> 等）。</p>
</blockquote>
<h2><a class="header" href="#closure-layout" id="closure-layout">Closure Layout</a></h2>
<h2><a class="header" href="#闭包的布局" id="闭包的布局">闭包的布局</a></h2>
<p>闭包的布局没有保证。</p>
<h2><a class="header" href="#representations" id="representations">Representations</a></h2>
<h2><a class="header" href="#表形表示形式" id="表形表示形式">表形/表示形式</a></h2>
<p>所有用户定义的复合类型（结构体(<code>struct</code>)、枚举(<code>enum</code>)和联合体(<code>union</code>)）都有一个*表形(representation)*属性，该属性用于指定该类型的布局。类型的可能表形有：</p>
<ul>
<li><a href="#the-default-representation">默认(default)表形</a></li>
<li><a href="#the-c-representation"><code>C</code>表形</a></li>
<li><a href="#primitive-representations">原语表形(primitive representation)</a></li>
<li><a href="#the-transparent-representation">透明表形(<code>transparent</code>)</a></li>
</ul>
<p>类型的表形可以通过对其应用 <code>repr</code>属性来更改。下面的示例展示了一个 <code>C</code>表形的结构体。</p>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>#[repr(C)]
struct ThreeInts {
    first: i16,
    second: i8,
    third: i32
}
<span class="boring">}
</span></code></pre></pre>
<p>可以分别使用 <code>align</code> 和 <code>packed</code> 修饰符增大或缩小对齐量。它们可以更改属性中指定表形的对齐量。如果未指定表形，则更改默认表形的。</p>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 默认表形，把对齐量缩小到2。
#[repr(packed(2))]
struct PackedStruct {
    first: i16,
    second: i8,
    third: i32
}

// C表形，把对齐量增大到8
#[repr(C, align(8))]
struct AlignedStruct {
    first: i16,
    second: i8,
    third: i32
}
<span class="boring">}
</span></code></pre></pre>
<blockquote>
<p>注意：由于表形是程序项的属性，因此表形不依赖于泛型参数。具有相同名称的任何两种类型都具有相同的表形。例如，<code>Foo&lt;Bar&gt;</code> 和 <code>Foo&lt;Baz&gt;</code> 都有相同的表形。</p>
</blockquote>
<p>类型的表形可以更改字段之间的填充，但不会更改字段本身的布局。例如一个使用 <code>C</code>表形的结构体，如果它包含一个默认表形的字段 <code>Inner</code>，那么它不会改变 <code>Inner</code> 的布局。</p>
<h3><a class="header" href="#the-default-representation" id="the-default-representation">The Default Representation</a></h3>
<h3><a class="header" href="#默认表形" id="默认表形">默认表形</a></h3>
<p>没有 <code>repr</code>属性的标称(nominal)类型具有默认表形。非正式地的情况下，也称这种表形为 <code>rust</code>表形。</p>
<p>这种表形不保证每次编译都有统一的数据布局。</p>
<h3><a class="header" href="#the-c-representation" id="the-c-representation">The <code>C</code> Representation</a></h3>
<h3><a class="header" href="#c表形" id="c表形"><code>C</code>表形</a></h3>
<p><code>C</code>表形被设计用于双重目的：一个目的是创建可以与 C语言互操作的类型；第二个目的是创建可以正确执行依赖于数据布局的操作的类型，比如将值重新解释为其他类型。</p>
<p>因为这种双重目的存在，可以只利用其中的一个目的，如只创建有固定布局的类型，而放弃与 C语言的互操作。</p>
<p>这种表型可以应用于结构体(structs)、联合体(unions)和枚举(enums)。一个例外是<a href="items/enumerations.html#zero-variant-enums">零变体枚举(zero-variant enums)</a>，它的 <code>C</code>表形是错误的。</p>
<h4><a class="header" href="#reprc-structs" id="reprc-structs"><code>#[repr(C)]</code> Structs</a></h4>
<h4><a class="header" href="#reprc结构体" id="reprc结构体"><code>#[repr(C)]</code>结构体</a></h4>
<p>结构体的对齐量是其*最大对齐量的字段(most-aligned field)*的对齐量。</p>
<p>字段的尺寸和偏移量则由以下算法确定：</p>
<ol>
<li>
<p>把当前偏移量设为从 0 字节开始。</p>
</li>
<li>
<p>对于结构体中的每个字段，按其声明的先后顺序，首先确定其尺寸和对齐量；如果当前偏移量不是对其齐量的整倍数，则向当前偏移量添加填充字节，直至其对齐量的倍数<sup class="footnote-reference"><a href="#译注1">1</a></sup>；至此，当前字段的偏移量就是当前偏移量；下一步再根据当前字段的尺寸增加当前偏移量。</p>
</li>
<li>
<p>最后，整个结构体的尺寸就是当前偏移量向上取整到结构体对齐量的最小整数倍数。</p>
</li>
</ol>
<p>下面用伪代码描述这个算法：</p>
<!-- ignore: pseudocode -->
<pre><code class="language-rust ignore">/// 返回偏移(`offset`)之后需要的填充量，以确保接下来的地址将被安排到可对齐的地址。
fn padding_needed_for(offset: usize, alignment: usize) -&gt; usize {
    let misalignment = offset % alignment;
    if misalignment &gt; 0 {
        // 向上取整到对齐量(`alignment`)的下一个倍数
        alignment - misalignment
    } else {
        // 已经是对齐量(`alignment`)的倍数了
        0
    }
}

struct.alignment = struct.fields().map(|field| field.alignment).max();

let current_offset = 0;

for field in struct.fields_in_declaration_order() {
    // 增加当前字的偏移量段(`current_offset`)，使其成为该字段对齐量的倍数。
    // 对于第一个字段，此值始终为零。
    // 跳过的字节称为填充字节。
    current_offset += padding_needed_for(current_offset, field.alignment);

    struct[field].offset = current_offset;

    current_offset += field.size;
}

struct.size = current_offset + padding_needed_for(current_offset, struct.alignment);
</code></pre>
<div class="warning">
<p>警告:这个伪代码使用了一个简单粗暴的算法，是为了清晰起见，它忽略了溢出问题。要在实际代码中执行内存布局计算，请使用 <a href="https://doc.rust-lang.org/std/alloc/struct.Layout.html"><code>Layout</code></a>。</p>
</div>
<blockquote>
<p>注意：此算法可以生成零尺寸的结构体。在 C 语言中，像 <code>struct Foo { }</code> 这样的空结构体声明是非法的。然而，gcc 和 clang 都支持启用此类结构体的选项，并将其尺寸指定为零。跟 Rust 不同的是 C++ 给空结构体指定的尺寸为 1，并且除非它们是继承的，否则它们是具有 <code>[[no_unique_address]]</code> 属性的字段（在这种情况下，它们不会增大结构体的整体尺寸）。</p>
</blockquote>
<h4><a class="header" href="#reprc-unions" id="reprc-unions"><code>#[repr(C)]</code> Unions</a></h4>
<h4><a class="header" href="#reprc联合体" id="reprc联合体"><code>#[repr(C)]</code>联合体</a></h4>
<p>使用 <code>#[repr(C)]</code> 声明的联合体将与相同目标平台上的 C语言中的 C联合体声明具有相同的尺寸和对齐量。联合体的对齐量等同于其所有字段的最大对齐量，尺寸将为其所有字段的最大尺寸，再对其向上取整到对齐量的最小整数倍。这些最大值可能来自不同的字段。</p>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>#[repr(C)]
union Union {
    f1: u16,
    f2: [u8; 4],
}

assert_eq!(std::mem::size_of::&lt;Union&gt;(), 4);  // 来自于 f2
assert_eq!(std::mem::align_of::&lt;Union&gt;(), 2); // 来自于 f1

#[repr(C)]
union SizeRoundedUp {
   a: u32,
   b: [u16; 5],
}

assert_eq!(std::mem::align_of::&lt;SizeRoundedUp&gt;(), 4); // 来自于 a

assert_eq!(std::mem::size_of::&lt;SizeRoundedUp&gt;(), 12);  // 首先来自于b的尺寸10，然后向上取整到最近的4的整数倍12。

<span class="boring">}
</span></code></pre></pre>
<h4><a class="header" href="#reprc-field-less-enums" id="reprc-field-less-enums"><code>#[repr(C)]</code> Field-less Enums</a></h4>
<h4><a class="header" href="#reprc无字段枚举" id="reprc无字段枚举"><code>#[repr(C)]</code>无字段枚举</a></h4>
<p>对于<a href="items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations">无字段枚举(field-less enums)</a>，<code>C</code>表形的尺寸和对齐量与目标平台的 C ABI 的默认枚举尺寸和对齐量相同。</p>
<blockquote>
<p>注意：C中的枚举的表形是由枚举的相应实现定义的，所以在 Rust 中，给无字段枚举应用 C表形得到的表型很可能是一个“最佳猜测”。特别是，当使用某些特定命令行参数来编译特定的 C代码时，这可能是不正确的。</p>
</blockquote>
<div class="warning">
<p>警告：C语言中的枚举与 Rust 中的那些应用了 <code>#[repr(C)]</code>表型的<a href="items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations">无字段枚举</a>之间有着重要的区别。C语言中的枚举主要是 <code>typedef</code> 加上一些具名常量；换句话说，C枚举(<code>enum</code>)类型的对象可以包含任何整数值。例如，C枚举通常被用做标志位。相比之下，Rust的<a href="items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations">无字段枚举</a>只能合法地<sup class="footnote-reference"><a href="#译注2">2</a></sup>保存判别式的值，其他的都是<a href="behavior-considered-undefined.html">未定义行为</a>。因此，在 FFI 中使用无字段枚举来建模 C语言中的枚举(<code>enum</code>)通常是错误的。</p>
</div>
<h4><a class="header" href="#reprc-enums-with-fields" id="reprc-enums-with-fields"><code>#[repr(C)]</code> Enums With Fields</a></h4>
<h4><a class="header" href="#reprc带字段枚举" id="reprc带字段枚举"><code>#[repr(C)]</code>带字段枚举</a></h4>
<p>带字段的 <code>repr(C)</code>枚举的表形其实等效于一个带两个字段的 <code>repr(C)</code>结构体（这种在 C语言中也被称为“标签联合(tagged union)”），这两个字段：</p>
<ul>
<li>一个为 <code>repr(C)</code>表形的枚举（在这个等效结构体内，它也被叫做标签(the tag)字段），它就是原枚举所有的判别值组合成的新枚举，也就是它的变体是原枚举变体移除了它们自身所带的所有字段。</li>
<li>一个为 <code>repr(C)</code>表形的联合体（在这个等效结构体内，它也被叫做载荷(the payload)字段），它的各个字段就是原枚举的各个变体把自己下面的字段重新组合成的 <code>repr(C)</code>表形的结构体。</li>
</ul>
<blockquote>
<p>注意：由于等效出的结构体和联合体是 <code>repr(C)</code>表形的，因此如果原来某一变体只有单个字段，则直接将该字段放入等效出的联合体中，或将其包装进一个次级结构体后再放入联合体中是没有区别的；因此，任何希望操作此类枚举表形的系统都可以选择使用这两种形式里对它们来说更方便或更一致的形式。</p>
</blockquote>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 这个枚举的表形等效于 ...
#[repr(C)]
enum MyEnum {
    A(u32),
    B(f32, u64),
    C { x: u32, y: u8 },
    D,
 }

// ... 这个结构体
#[repr(C)]
struct MyEnumRepr {
    tag: MyEnumDiscriminant,
    payload: MyEnumFields,
}

// 这是原判别值组成的新枚举类型.
#[repr(C)]
enum MyEnumDiscriminant { A, B, C, D }

// 这是原变体的字段组成的联合体.
#[repr(C)]
union MyEnumFields {
    A: MyAFields,   // 译者注：因为原枚举变体A只有一个字段，所以此处的类型标注也可以直接替换为 u32,以省略 MyAFields这层封装
    B: MyBFields,
    C: MyCFields,
    D: MyDFields,
}

#[repr(C)]
#[derive(Copy, Clone)]
struct MyAFields(u32);

#[repr(C)]
#[derive(Copy, Clone)]
struct MyBFields(f32, u64);

#[repr(C)]
#[derive(Copy, Clone)]
struct MyCFields { x: u32, y: u8 }

// 这个结构体可以被省略(它是一个零尺寸类型)，但它必须出现在 C/C++ 头文件中
#[repr(C)]
#[derive(Copy, Clone)]
struct MyDFields;
<span class="boring">}
</span></code></pre></pre>
<blockquote>
<p>注意： 联合体(<code>union</code>)可带有未实现 <code>Copy</code> 的字段的功能还没有纳入稳定版，具体参见 <a href="https://github.com/rust-lang/rust/issues/55149">55149</a>。</p>
</blockquote>
<h3><a class="header" href="#primitive-representations" id="primitive-representations">Primitive representations</a></h3>
<h3><a class="header" href="#原语表形" id="原语表形">原语表形</a></h3>
<p><em>原语表形</em>是与原生整型具有相同名称的表形。也就是：<code>u8</code>，<code>u16</code>，<code>u32</code>，<code>u64</code>，<code>u128</code>，<code>usize</code>，<code>i8</code>，<code>i16</code>，<code>i32</code>，<code>i64</code>，<code>i128</code> 和 <code>isize</code>。</p>
<p>原语表形只能应用于枚举，此时枚举有没有字段会给原语表形带来不同的表现。给<a href="items/enumerations.html#zero-variant-enums">零变体枚举</a>应用原始表形是错误的。将两个原语表形组合在一起也是错误的</p>
<h4><a class="header" href="#primitive-representation-of-field-less-enums" id="primitive-representation-of-field-less-enums">Primitive Representation of Field-less Enums</a></h4>
<h4><a class="header" href="#无字段枚举的原语表形" id="无字段枚举的原语表形">无字段枚举的原语表形</a></h4>
<p>对于<a href="items/enumerations.html#custom-discriminant-values-for-fieldless-enumerations">无字段枚举</a>，原语表形将其尺寸和对齐量设置成与给定表形同名的原生类型的表形的值。例如，一个 <code>u8</code>表形的无字段枚举只能有0和255之间的判别值。</p>
<h4><a class="header" href="#primitive-representation-of-enums-with-fields" id="primitive-representation-of-enums-with-fields">Primitive Representation of Enums With Fields</a></h4>
<h4><a class="header" href="#带字段枚举的原语表形" id="带字段枚举的原语表形">带字段枚举的原语表形</a></h4>
<p>带字段枚举的原语表形是一个 <code>repr(C)</code>表形的联合体，此联合体的每个字段对应一个和原枚举变体对应的 <code>repr(C)</code>表形的结构体。这些结构体的第一个字段是原枚举的变体移除了它们所有的字段组成的原语表形版的无字段枚举（“the tag”），那这些结构体的其余字段是原变体移走的字段。</p>
<blockquote>
<p>注意：如果在联合体中，直接把标签的成员赋予给标签(“the tag”)，那么这种表形结构仍不变的，并且这样操作对您来说可能会更清晰（尽管遵循 c++ 的标准，标签也应该被包装在结构体中）。</p>
</blockquote>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>// 这个枚举的表形效同于 ...
#[repr(u8)]
enum MyEnum {
    A(u32),
    B(f32, u64),
    C { x: u32, y: u8 },
    D,
 }

// ... 这个联合体.
#[repr(C)]
union MyEnumRepr {
    A: MyVariantA,  //译者注：此字段类型也可直接用 u32 直接替代
    B: MyVariantB,  //译者注：此字段类型也可直接用 (f32, u64) 直接替代
    C: MyVariantC,
    D: MyVariantD,
}

// 这是原判别值组合成的新枚举。
#[repr(u8)]
#[derive(Copy, Clone)]
enum MyEnumDiscriminant { A, B, C, D }

#[repr(C)]
#[derive(Clone, Copy)]
struct MyVariantA(MyEnumDiscriminant, u32);

#[repr(C)]
#[derive(Clone, Copy)]
struct MyVariantB(MyEnumDiscriminant, f32, u64);

#[repr(C)]
#[derive(Clone, Copy)]
struct MyVariantC { tag: MyEnumDiscriminant, x: u32, y: u8 }

#[repr(C)]
#[derive(Clone, Copy)]
struct MyVariantD(MyEnumDiscriminant);
<span class="boring">}
</span></code></pre></pre>
<blockquote>
<p>注意： 联合体(<code>union</code>)带有未实现 <code>Copy</code> trait 的字段的功能还没有纳入稳定版，具体参见 <a href="https://github.com/rust-lang/rust/issues/55149">55149</a>。</p>
</blockquote>
<h4><a class="header" href="#combining-primitive-representations-of-enums-with-fields-and-reprc" id="combining-primitive-representations-of-enums-with-fields-and-reprc">Combining primitive representations of enums with fields and <code>#[repr(C)]</code></a></h4>
<h4><a class="header" href="#带字段枚举的原语表形与reprc表形的组合使用" id="带字段枚举的原语表形与reprc表形的组合使用">带字段枚举的原语表形与<code>#[repr(C)]</code>表形的组合使用</a></h4>
<p>对于带字段枚举，还可以将 <code>repr(C)</code> 和原语表形（例如，<code>repr(C, u8)</code>）结合起来使用。这是通过将判别值组成的枚举的表形改为原语表形来实现的。因此，如果选择组合 <code>u8</code>表形，那么组合出的判别值枚举的尺寸和对齐量将为 1 个字节。</p>
<p>那么这个判别值枚举就从<a href="#reprc-enums-with-fields">前面</a>示例中的样子变成：</p>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>#[repr(C, u8)] // 这里加上了 `u8`
enum MyEnum {
    A(u32),
    B(f32, u64),
    C { x: u32, y: u8 },
    D,
 }

// ...

#[repr(u8)] // 所以这里就用 `u8` 替代了 `C`
enum MyEnumDiscriminant { A, B, C, D }

// ...
<span class="boring">}
</span></code></pre></pre>
<p>例如，对于有 <code>repr(C, u8)</code>属性的枚举，不可能有257个唯一的判别值（“tags”），而同一个枚举，如果只有单一 <code>repr(C)</code>表形属性，那在编译时就不会出任何问题。</p>
<p>在 <code>repr(C)</code> 附加原语表形可以改变 <code>repr(C)</code>表形的枚举的尺寸：</p>
<pre><pre class="playground"><code class="language-rust edition2018">
<span class="boring">#![allow(unused)]
</span><span class="boring">fn main() {
</span>#[repr(C)]
enum EnumC {
    Variant0(u8),
    Variant1,
}

#[repr(C, u8)]
enum Enum8 {
    Variant0(u8),
    Variant1,
}

#[repr(C, u16)]
enum Enum16 {
    Variant0(u8),
    Variant1,
}

// C表形的尺寸依赖于平台
assert_eq!(std::mem::size_of::&lt;EnumC&gt;(), 8);
// 一个字节用于判别值，一个字节用于 Enum8::Variant0 中的值
assert_eq!(std::mem::size_of::&lt;Enum8&gt;(), 2);
// 两个字节用于判别值，一个字节用于Enum16::Variant0中的值，加上一个字节的填充
assert_eq!(std::mem::size_of::&lt;Enum16&gt;(), 4);
<span class="boring">}
</span></code></pre></pre>
<h3><a class="header" href="#the-alignment-modifiers" id="the-alignment-modifiers">The alignment modifiers</a></h3>
<h3><a class="header" href="#对齐量的修饰符" id="对齐量的修饰符">对齐量的修饰符</a></h3>
<p><code>align</code> 和 <code>packed</code> 修饰符可分别用于增大和减小结构体的和联合体的对齐量。<code>packed</code> 也可以改变字段之间的填充。</p>
<p>对齐量被指定为整型参数，形式为 <code>#[repr(align(x))]</code> 或 <code>#[repr(packed(x))]</code>。对齐量的值必须是从1到2<sup>29</sup>之间的2的次幂数。对于 <code>packed</code>，如果没有给出任何值，如 <code>#[repr(packed)]</code>，则对齐量的值为1。</p>
<p>对于 <code>align</code>，如果类型指定的对齐量比其不带 <code>align</code>修饰符时的对齐量小，则该指定的对齐量无效。</p>
<p>对于 <code>packed</code>，如果类型指定的对齐量比其不带 <code>packed</code>修饰符时的对齐量大，则该指定的对齐量和布局无效。为了定位字段，每个字段的对齐量是指定的对齐量和字段的类型的对齐量中较小的那个对齐量。</p>
<p><code>align</code> 和 <code>packed</code> 修饰符不能应用于同一类型，且 <code>packed</code> 修饰的类型不能直接或间接地包含另一个 <code>align</code> 修饰的类型。<code>align</code> 和 <code>packed</code> 修饰符只能应用于<a href="#the-default-representation">默认表形</a>和 <a href="#the-c-representation">C表形</a>中。</p>
<p><code>align</code>修饰符也可以应用在枚举上。如果这样做了，其对枚举对齐量的影响与将此枚举包装在一个新的使用了相同的 <code>align</code>修饰符的结构体中的效果相同。</p>
<div class="warning">
<p>***警告：***解引用一个未对齐的指针是<a href="behavior-considered-undefined.html">未定义行为</a>，但可以<a href="https://github.com/rust-lang/rust/issues/27060">安全地创建指向 <code>packed</code>修饰的字段的未对齐指针</a>。就像在安全(safe) Rust 中所有创建未定义行为的方法一样，这是一个 bug。</p>
</div>
<h3><a class="header" href="#the-transparent-representation" id="the-transparent-representation">The <code>transparent</code> Representation</a></h3>
<h3><a class="header" href="#透明transparent表形" id="透明transparent表形">透明(<code>transparent</code>)表形</a></h3>
<p>透明(<code>transparent</code>)表型只能在只有一个字段的<a href="items/structs.html">结构体(<code>struct</code>)</a>上或只有一个变体的<a href="items/enumerations.html">枚举(<code>enum</code>)</a>上使用，这里只有一个字段/变体的意思是：</p>
<ul>
<li>只能有一个非零尺寸的字段/变体，和</li>
<li>任意数量的尺寸为零对齐量为1的字段（例如：<a href="special-types-and-traits.html#phantomdatat"><code>PhantomData&lt;T&gt;</code></a>）</li>
</ul>
<p>使用这种表形的结构体和枚举与只有那个非零尺寸的字段具有相同的布局和 ABI。</p>
<p>这与 <code>C</code>表形不同，因为带有 <code>C</code>表形的结构体将始终拥有 C结构体(<code>C</code> <code>struct</code>)的ABI，例如，那些只有一个原生类型字段的结构体如果应用了透明表形(<code>transparent</code>)，将具有此原生类型字段的ABI。</p>
<p>因为此表形将类型布局委托给另一种类型，所以它不能与任何其他表形一起使用。</p>
<div class="footnote-definition" id="译注1"><sup class="footnote-definition-label">1</sup>
<p>至此，上一个字段就填充完成，开始计算本字段了。也就是说每一个字段的偏移量是其字段的段首位置；那第一个字段的偏移量就始终为 0。</p>
</div>
<div class="footnote-definition" id="译注2"><sup class="footnote-definition-label">2</sup>
<p>这里合法的意思是变体的判别值受 <code>repr(u8)</code> 这样的表形属性约束，像这个例子中，变体的判别值就只能位于 0~255 之间。 </p>
</div>
<!-- 2020-12-17-->
<!-- checked -->

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="dynamically-sized-types.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="interior-mutability.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a rel="prev" href="dynamically-sized-types.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a rel="next" href="interior-mutability.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>

        

        

        

        
        <script type="text/javascript">
            window.playground_copyable = true;
        </script>
        

        

        
        <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="searcher.js" type="text/javascript" charset="utf-8"></script>
        

        <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        

        

    </body>
</html>
